﻿/*
* Helium Client
* Open source based on Attribution-NonCommercial 4.0 International
* Utils by MacroModel
*/
#pragma once

#include <cstddef>
#include <type_traits>
#include <string>
#include <windows.h>
#include <Psapi.h>
//#include <future>
#undef min
#undef max
#include <fast_io/fast_io.h>
#include <fast_io/fast_io_freestanding.h>

#include "HCNMath.h"

namespace Utils {

inline static constexpr std::u8string_view KeyNames[] = {
	u8"Unknown",
	u8"VK_LBUTTON",
	u8"VK_RBUTTON",
	u8"VK_CANCEL",
	u8"VK_MBUTTON",
	u8"VK_XBUTTON1",
	u8"VK_XBUTTON2",
	u8"Unknown",
	u8"VK_BACK",
	u8"TAB",
	u8"Unknown",
	u8"Unknown",
	u8"VK_CLEAR",
	u8"VK_RETURN",
	u8"Unknown",
	u8"Unknown",
	u8"Shift",
	u8"CTRL",
	u8"VK_MENU",
	u8"VK_PAUSE",
	u8"VK_CAPITAL",
	u8"VK_KANA",
	u8"Unknown",
	u8"VK_JUNJA",
	u8"VK_FINAL",
	u8"VK_KANJI",
	u8"Unknown",
	u8"VK_ESCAPE",
	u8"VK_CONVERT",
	u8"VK_NONCONVERT",
	u8"VK_ACCEPT",
	u8"VK_MODECHANGE",
	u8"VK_SPACE",
	u8"VK_PRIOR",
	u8"VK_NEXT",
	u8"VK_END",
	u8"VK_HOME",
	u8"VK_LEFT",
	u8"VK_UP",
	u8"VK_RIGHT",
	u8"VK_DOWN",
	u8"VK_SELECT",
	u8"VK_PRINT",
	u8"VK_EXECUTE",
	u8"VK_SNAPSHOT",
	u8"INSERT",
	u8"DELETE",
	u8"VK_HELP",
	u8"0",
	u8"1",
	u8"2",
	u8"3",
	u8"4",
	u8"5",
	u8"6",
	u8"7",
	u8"8",
	u8"9",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"A",
	u8"B",
	u8"C",
	u8"D",
	u8"E",
	u8"F",
	u8"G",
	u8"H",
	u8"I",
	u8"J",
	u8"K",
	u8"L",
	u8"M",
	u8"N",
	u8"O",
	u8"P",
	u8"Q",
	u8"R",
	u8"S",
	u8"T",
	u8"U",
	u8"V",
	u8"W",
	u8"X",
	u8"Y",
	u8"Z",
	u8"VK_LWIN",
	u8"VK_RWIN",
	u8"VK_APPS",
	u8"Unknown",
	u8"VK_SLEEP",
	u8"NUMPAD0",
	u8"NUMPAD1",
	u8"NUMPAD2",
	u8"NUMPAD3",
	u8"NUMPAD4",
	u8"NUMPAD5",
	u8"NUMPAD6",
	u8"NUMPAD7",
	u8"NUMPAD8",
	u8"NUMPAD9",
	u8"VK_MULTIPLY",
	u8"VK_ADD",
	u8"VK_SEPARATOR",
	u8"VK_SUBTRACT",
	u8"VK_DECIMAL",
	u8"VK_DIVIDE",
	u8"F1",
	u8"F2",
	u8"F3",
	u8"F4",
	u8"F5",
	u8"F6",
	u8"F7",
	u8"F8",
	u8"F9",
	u8"F10",
	u8"F11",
	u8"F12",
	u8"VK_F13",
	u8"VK_F14",
	u8"VK_F15",
	u8"VK_F16",
	u8"VK_F17",
	u8"VK_F18",
	u8"VK_F19",
	u8"VK_F20",
	u8"VK_F21",
	u8"VK_F22",
	u8"VK_F23",
	u8"VK_F24",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"VK_NUMLOCK",
	u8"VK_SCROLL",
	u8"VK_OEM_NEC_EQUAL",
	u8"VK_OEM_FJ_MASSHOU",
	u8"VK_OEM_FJ_TOUROKU",
	u8"VK_OEM_FJ_LOYA",
	u8"VK_OEM_FJ_ROYA",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"Unknown",
	u8"LeftShift",
	u8"RightShift",
	u8"VK_LCONTROL",
	u8"VK_RCONTROL",
	u8"VK_LMENU",
	u8"VK_RMENU",
	u8"Browser Back",
	u8"Browser Forward",
	u8"Browser Refresh",
	u8"Browser Stop",
	u8"Browser Search",
	u8"Browser Favourites",
	u8"Browser Home",
	u8"Volume Mute",
	u8"Volume Down",
	u8"Volume Up",
	u8"Media_Next",
	u8"Media_Prev",
	u8"Media_Stop",
	u8"Media_Pause",
	u8"Mail",
	u8"Media",
	u8"App1",
	u8"App2",
	u8"Unknown",
	u8"Unknown",
	u8"OEM_1",
	u8"PLUS",
	u8"COMMA",
	u8"MINUS",
	u8"DOT",
	u8"OEM_2",
	u8"OEM_3"
};

struct TextColor {

	static constexpr char8_t BLACK[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'0', u8'\0'};
	static constexpr char8_t DARK_BLUE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'1', u8'\0'};
	static constexpr char8_t DARK_GREEN[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'2', u8'\0'};
	static constexpr char8_t DARK_AQUA[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'3', u8'\0'};
	static constexpr char8_t DARK_RED[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'4', u8'\0'};
	static constexpr char8_t DARK_PURPLE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'5', u8'\0'};
	static constexpr char8_t GOLD[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'6', u8'\0'};
	static constexpr char8_t GRAY[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'7', u8'\0'};
	static constexpr char8_t DARK_GRAY[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'8', u8'\0'};
	static constexpr char8_t BLUE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'9', u8'\0'};
	static constexpr char8_t GREEN[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'a', u8'\0'};
	static constexpr char8_t AQUA[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'b', u8'\0'};
	static constexpr char8_t RED[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'c', u8'\0'};
	static constexpr char8_t LIGHT_PURPLE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'd', u8'\0'};
	static constexpr char8_t YELLOW[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'e', u8'\0'};
	static constexpr char8_t WHITE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'f', u8'\0'};

	static constexpr char8_t OBFUSCATED[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'k', u8'\0'};
	static constexpr char8_t BOLD[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'l', u8'\0'};
	static constexpr char8_t STRIKETHROUGH[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'm', u8'\0'};
	static constexpr char8_t UNDERLINE[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'n', u8'\0'};
	static constexpr char8_t ITALIC[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'o', u8'\0'};
	static constexpr char8_t RESET[4] = {(char8_t)0xC2, (char8_t)0xA7, u8'r', u8'\0'};

};

struct Ver {
	uint16_t f{};
	uint16_t s{};
};

class Utils final {
public:
#ifdef _DEBUG
	static constexpr std::u8string_view ClientName = u8"Helium Dev";
	static constexpr Ver Version{1, 0};
#elif defined _GHOST
	static constexpr std::u8string_view ClientName = u8"Helium Ghost";
	static constexpr Ver Version{1, 0};
#else   // Pro
	static constexpr std::u8string_view ClientName = u8"Helium Pro";
	static constexpr Ver Version{1, 0};
#endif  // _DEBUG
	static const std::u8string RoamingStateFold;
	static const uintptr_t CachedBase;
	static MODULEINFO Minecraft_MODULEINFO;
	static HMODULE helium_HMODULE;
	static MODULEINFO helium_MODULEINFO;
	static LPVOID helium_LPVOID;

	static fast_io::net_service service;

public:

	static uintptr_t getBase() noexcept;

	static __forceinline constexpr bool InASCIIChar(uint8_t c) noexcept {
		return c < 128ui8;
	}

	template <typename _Ty>
	static __forceinline constexpr void ImSwap(_Ty& a, _Ty& b) noexcept {
		_Ty tmp = a;
		a = b;
		b = tmp;
	}

	template <size_t IIdx, typename TRet, typename... TArgs>
	static inline constexpr auto CallVFunc(void* thisptr, TArgs... argList) -> TRet {
		using Fn = TRet(__thiscall*)(void*, decltype(argList)...);
		return (*static_cast<Fn**>(thisptr))[IIdx](thisptr, argList...);
	}

	template <typename ret>
	static inline constexpr auto FuncFromSigOffset(uintptr_t sig, int32_t offset) noexcept -> ret {
		return reinterpret_cast<ret>(sig + offset + 4 + *reinterpret_cast<uintptr_t*>(sig + offset));
	}

	__forceinline static constexpr auto RotBy(int32_t in, uint32_t by) noexcept -> uint64_t {
		return ((static_cast<uint64_t>(in) & 0x7FFFFFui64) | ((static_cast<uint32_t>(in) >> 8u) & 0x800000u) /*copy sign bit*/) << by;
	}

	__forceinline static constexpr auto PosToHash(const vec3_ti pos) noexcept -> uint64_t {
		return RotBy(pos.x, 0u) | RotBy(pos.z, 24u) | (static_cast<uint64_t>(pos.y) << 48u);
	}

private:
	__forceinline static constexpr auto GetCrc32Lut() noexcept -> fast_io::freestanding::array<uint32_t, 256> {
		fast_io::freestanding::array<uint32_t, 256> res{};
		constexpr uint32_t polynomial = 0xEDB88320ui32;
		for (uint32_t i = 0; i < 256; ++i) {
			uint32_t crc = i;
			for (size_t j = 0; j < 8; ++j)
				crc = (crc >> 1) ^ (((uint32_t)(-((int32_t)(crc & 1)))) & polynomial);
			res[i] = crc;
		}
		return res;
	}

public:
	inline static constexpr auto GetCrcHash(const std::u8string_view sv, int32_t seed = 0) noexcept -> uint32_t {
		constexpr auto crc32_lut = GetCrc32Lut();
		seed = ~seed;
		uint32_t crc = seed;
		for (size_t i = 0; i < sv.length() - 1; ++i) {
			if (sv[i] == '#' && sv[i + 1] == '#')
				crc = seed;
			crc = (crc >> 8) ^ crc32_lut[(crc & 0xFFui32) ^ sv[i]];
		}
		return ~crc;
	}

	inline static constexpr auto GetKeybindName(size_t keybind) noexcept -> std::u8string_view {
		return KeyNames[keybind];
	};

	inline static constexpr auto ColorConvertRGBtoHSV(const vec3_t rgb) noexcept -> vec3_t {
		float r = rgb.x;
		float g = rgb.y;
		float b = rgb.z;

		float K = 0.f;
		if (g < b) {
			ImSwap(g, b);
			K = -1.f;
		}
		if (r < g) {
			ImSwap(r, g);
			K = -2.f / 6.f - K;
		}

		const float chroma = r - (g < b ? g : b);
		const float out_h = ImmeMath::abs_imme(K + (g - b) / (6.f * chroma + 1e-20f));
		const float out_s = chroma / (r + 1e-20f);
		const float out_v = r;
		return vec3_t{out_h, out_s, out_v};
	};

	inline static constexpr auto ColorConvertHSVtoRGB(const vec3_t hsv) noexcept -> vec3_t {
		const float h = ImmeMath::mod_imme(hsv.x, 1.0f) / (60.0f / 360.0f);
		const float s = hsv.y;
		const float v = hsv.z;

		float out_r, out_g, out_b;

		if (s == 0.0f) [[unlikely]]
			return vec3_t{v, v, v};

		int64_t i = (int64_t)h;
		float f = h - (float)i;
		float p = v * (1.0f - s);
		float q = v * (1.0f - s * f);
		float t = v * (1.0f - s * (1.0f - f));

		switch (i) {
		case 0:
			out_r = v;
			out_g = t;
			out_b = p;
			break;
		case 1:
			out_r = q;
			out_g = v;
			out_b = p;
			break;
		case 2:
			out_r = p;
			out_g = v;
			out_b = t;
			break;
		case 3:
			out_r = p;
			out_g = q;
			out_b = v;
			break;
		case 4:
			out_r = t;
			out_g = p;
			out_b = v;
			break;
		case 5:
		default:
			out_r = v;
			out_g = p;
			out_b = q;
			break;
		}
		return vec3_t{out_r, out_g, out_b};
	};

	inline static constexpr void ApplyRainbow(MC_Color& rcolors, const float modifier = 0.003f) noexcept {
		if (rcolors.a < 1) {
			rcolors.r = 1;
			rcolors.g = 0.6f;
			rcolors.b = 0.6f;
			rcolors.a = 1;
		}

		const auto hsv = Utils::ColorConvertRGBtoHSV(vec3_t{rcolors.r, rcolors.g, rcolors.b});
		auto hsv_x = hsv.x + modifier;
		if (hsv_x >= 1.f)
			hsv_x = 0.f;
		const auto rgb = Utils::ColorConvertHSVtoRGB({hsv_x});

		rcolors.r = rgb.x;
		rcolors.g = rgb.y;
		rcolors.b = rgb.z;
	}

	static std::u8string Base64Encode(const std::u8string_view in) noexcept;

	static std::u8string Base64Decode(const std::u8string_view in) noexcept;

	static std::u8string RandomString(const size_t size) noexcept;

	static std::u8string GetClipboardText() noexcept;

	static void SetClipboardText(const std::u8string_view text) noexcept;

	static fast_io::native_file_loader ReadFileContents(const std::u8string_view filePath);  // fast_io

	static void SystemPlaySound(std::u8string_view name) noexcept;

	static std::u8string GetRoamingFolderPath() noexcept;

	/*****************
	* Find Signature *
	*****************/

	inline static constexpr size_t StrToSignatureSize(const std::string_view szSignature) noexcept {
		size_t size = 0;

		constexpr auto check = [](uint8_t str)  -> bool {
			return (str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z') || (str >= '0' && str <= '9');
		};

		size_t reset = 0;  // Erase '?' at the end

		for (size_t i = 0; i < szSignature.length(); ++i) {
			if (szSignature[i] == ' ')
				continue;
			else if (check(szSignature[i])) {
				reset = 0;
				++size;
				if (i + 1 < szSignature.length() && check(szSignature[i + 1]))
					++i;
			} else if (szSignature[i] == '?') {
				++reset;
				++size;
				if (i + 1 < szSignature.length() && szSignature[i + 1] == '?')
					++i;
			}
		}
		return size - reset;
	}

	template <size_t Size>
	inline static constexpr fast_io::freestanding::array<uint16_t, Size> StrToSignatureArray(const std::string_view szSignature) noexcept {
		fast_io::freestanding::array<uint16_t, Size> signature_result{0ui16};

		constexpr auto check = [](uint8_t str)  -> bool {
			return (str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z') || (str >= '0' && str <= '9');
		};

		constexpr auto HexToOct = [](uint8_t str)  -> uint8_t {
			if (str >= 'a' && str <= 'z')
				return str - 'a' + 10ui8;
			else if (str >= 'A' && str <= 'Z')
				return str - 'A' + 10ui8;
			else if (str >= '0' && str <= '9')
				return str - '0';
			else
				return 0ui8;
		};

		size_t s_i = 0;
		for (size_t i = 0; i < szSignature.length() && s_i < szSignature.size(); ++i) {
			if (szSignature[i] == ' ')
				continue;
			else if (check(szSignature[i])) {
				if (i + 1 < szSignature.length() && check(szSignature[i + 1])) {
					signature_result[s_i++] = (HexToOct(szSignature[i]) << 4) | HexToOct(szSignature[i + 1]);
					++i;
				} else
					signature_result[s_i++] = HexToOct(szSignature[i]);
			} else if (szSignature[i] == '?') {
				if (i + 1 < szSignature.length() && szSignature[i + 1] == '?') // "??"
					++i;
				signature_result[s_i++] = 0xffffui16;
			}
		}

		return signature_result;
	}

	template <size_t Size>
	inline static constexpr fast_io::freestanding::array<size_t, 256> Pretreatment(const fast_io::freestanding::array<uint16_t, Size> szSignature) noexcept {
		fast_io::freestanding::array<size_t, 256> result{}; 
		size_t res_counter = 0;
		for (size_t i = 0; i < szSignature.size(); ++i) {
			if (res_counter >= 256)
				break;
			if (const auto str = szSignature[i]; str != 0xffffui16 && result[str] == 0) {
				++res_counter;
				size_t fallbackSize = 1;
				for (size_t f_i = szSignature.size(); f_i > 0; --f_i)
					if (szSignature[f_i - 1] == str)  // alignment
						break;
					else  // '?' or others
						++fallbackSize;
				result[str] = fallbackSize;
			}
		}
		// '?' alignment
		size_t anysign_counter = szSignature.size();
		for (; anysign_counter > 0 && szSignature[anysign_counter - 1] != 0xffffui16; --anysign_counter) 
			if (szSignature[anysign_counter - 1] == 0xffffui16) 
				break;
		if (anysign_counter != 0) 
			for (size_t i = 0; i < 256; ++i)
				if (result[i] == 0 || result[i] > szSignature.size() - anysign_counter + 1)
					result[i] = szSignature.size() - anysign_counter + 1;
		return result;
	}

	template <size_t Size>
	static uintptr_t FindSignatureModule(const fast_io::freestanding::array<uint16_t, Size> szSignature, fast_io::freestanding::array<size_t, 256> Table) noexcept {  // Find the 'times' occurrence in memory
		//======================
		// GetModuleHandleA
		static const uintptr_t rangeEnd = CachedBase + Minecraft_MODULEINFO.SizeOfImage;
		//======================

		if (szSignature.size() > rangeEnd - CachedBase) [[unlikely]]
			return 0;

		//const auto Table = Pretreatment<Size>(szSignature);  // Pretreatment Table

		for (uintptr_t i = CachedBase; i < rangeEnd;) { 
			size_t move_back_size = 0;
			if (*reinterpret_cast<uint8_t*>(i) == szSignature.front()) {
				size_t fallbackSize = 1;
				uint8_t last_char = 0ui8;
				for (; fallbackSize < szSignature.size() && i + fallbackSize < rangeEnd; ++fallbackSize) {
					if (szSignature[fallbackSize] != 0xffffui16 && *reinterpret_cast<uint8_t*>(i + fallbackSize) != szSignature[fallbackSize]) {  // '?' or the same
						last_char = static_cast<uint8_t>(szSignature[fallbackSize]);
						break;
					}
				}
				if (fallbackSize == szSignature.size()) [[unlikely]]  // Match All
					return i;
				else [[likely]] { // KMP
					for (uintptr_t i2 = i + fallbackSize + 1; i2 < rangeEnd; ++i2) {
						if (*reinterpret_cast<uint8_t*>(i2) == last_char) [[unlikely]] { // Find the closest character alignment
							move_back_size = i2 - (i + fallbackSize);
							break;
						}
						if (i2 == rangeEnd - 1) [[unlikely]]
							return 0;
					}
				}
			}
			if (i + szSignature.size() < rangeEnd) [[likely]] {  // Sunday
				// The maximum number of displacements required for a char after the end of the comparison
				if (const auto str = *reinterpret_cast<uint8_t*>(i + szSignature.size()); Table[str] != 0) [[likely]] {  // The preprocessed data does not exist
					if (move_back_size < Table[str]) // Take maximum alignment
						move_back_size = Table[str];
				} else [[unlikely]] {
					if (move_back_size < szSignature.size() + 1)  // Take maximum alignment
						move_back_size = szSignature.size() + 1;  // alignment
				}
			} else [[unlikely]]
				return 0;
			i += move_back_size;
		}
		return 0;
	}

	//[[noreturn]] static void MakeFold(const std::u8string_view file) ;

	static std::u8string GetLocalTime_string(); // use fast_io::posix_tzset() to calibration

	inline static fast_io::iso8601_timestamp GetLocalTime() {  // use fast_io::posix_tzset() to calibration
		return local(fast_io::posix_clock_gettime(fast_io::posix_clock_id::realtime));
	}

	static void patchBytes(void* dst, void* src, size_t size);

	static void nopBytes(void* dst, size_t size);

public:

	static constexpr char8_t dec2hexChar(char8_t n) noexcept {
		if (0 <= n && n <= 9) {
			return u8'0' + n;
		} else if (10 <= n && n <= 15) {
			return u8'A' + n - 10;
		} else {
			return 0;
		}
	}

	static constexpr char8_t hexChar2dec(char8_t c) noexcept {
		if (u8'0' <= c && c <= u8'9') {
			return c - u8'0';
		} else if (u8'a' <= c && c <= u8'f') {
			return c - u8'a' + 10;
		} else if ('A' <= c && c <= 'F') {
			return c - u8'A' + 10;
		} else {
			return -1;
		}
	}

public:
	static std::u8string escapeURL(std::u8string_view sv);

	static std::u8string deescapeURL(std::u8string_view sv);
};

namespace base64_imme { // Base64

inline static constexpr std::u8string_view Base64Alphabet{u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};

// https://stackoverflow.com/a/34571089/3158571
// Base64 Encode
template <size_t N>
static constexpr auto Base64Encode_imme(const std::u8string_view s) noexcept -> fast_io::freestanding::array<char8_t, N> {
	fast_io::freestanding::array<char8_t, N> bytes{};

	int32_t valb = -6;
	uint32_t val = 0ui32;
	size_t posOut = 0;

	for (size_t i = 0; i < s.length(); ++i) {
		val = (val << 8) + s[i];
		valb += 8;
		for (; valb >= 0; valb -= 6)
			bytes[posOut++] = Base64Alphabet[(val >> valb) & 0x3Fui32];
	}

	if (valb > -6)
		bytes[posOut++] = Base64Alphabet[(((uint64_t)val << 8) >> (valb + 8)) & 0x3Fui32];

	const int32_t equalsize = 4 - posOut % 4;
	if (equalsize == 2) {
		bytes[bytes.size() - 3] = u8'=';
		bytes[bytes.size() - 2] = u8'=';
	} else if (equalsize == 1)
		bytes[bytes.size() - 2] = u8'=';
	bytes.back() = (char8_t)0;  // Last digit modified '0'
	return bytes;
}

static constexpr auto Base64EncodeFixedLength(const std::u8string_view s) noexcept -> size_t {
	return (s.length() + 2) / 3 * 4 + 1;
}

// Base64Decode
constexpr auto Base64DecodeTable() noexcept -> fast_io::freestanding::array<char8_t, 256> {
	fast_io::freestanding::array<char8_t, 256> Table{};
	for (size_t i = 0; i < 256; ++i)
		Table[i] = (char8_t)255; 
	for (uint8_t i = 0; i < 64; ++i)
		Table[Base64Alphabet[i]] = i;
	return Table;
}

template <size_t N>
constexpr auto Base64Decode_imme(const std::u8string_view s) noexcept -> fast_io::freestanding::array<char8_t, N> {
	constexpr auto Table = Base64DecodeTable();
	fast_io::freestanding::array<char8_t, N> bytes{};
	int32_t valb = -8;
	uint32_t val = 0ui32;
	for (size_t i = 0, posOut = 0; i < s.length() && Table[s[i]] != 255ui8; ++i) {
		val = (val << 6) + Table[s[i]];
		valb += 6;
		if (valb >= 0) {
			bytes[posOut++] = (val >> valb) & 0xFFui32;
			valb -= 8;
		}
	}
	bytes.back() = 0i8;  // Last digit modified '0'
	return bytes;
}

// Infer the decoded u8string length from the end
constexpr auto Base64DecodeFixedLength(const std::u8string_view s) noexcept -> size_t {
	const auto len = (s.length() / 4) * 3 + 1;  // Add '0' to the last digit
	if (s[s.length() - 2] == u8'=')
		return len - 2;
	else if (s[s.length() - 1] == u8'=')
		return len - 1;
	else
		return len;
}
}  // namespace base64imme
}  // namespace Utils

#define B64EncodeResult(x) Utils::base64_imme::Base64Encode_imme<Utils::base64_imme::Base64EncodeFixedLength(x)>(x)
#define B64DecodeResult(x) Utils::base64_imme::Base64Decode_imme<Utils::base64_imme::Base64DecodeFixedLength(x)>(x)

#define FindSignature(x) []() { constexpr auto temp = Utils::Utils::StrToSignatureArray<Utils::Utils::StrToSignatureSize(x)>(x); constexpr auto table = Utils::Utils::Pretreatment(temp); return Utils::Utils::FindSignatureModule(temp, table); }()
//#define FindSignatureAsync(x)  []() { constexpr auto temp = Utils::Utils::StrToSignatureArray<Utils::Utils::StrToSignatureSize(x)>(x); constexpr auto table = Utils::Utils::Pretreatment(temp);  return std::async(std::launch::async | std::launch::deferred, Utils::Utils::FindSignatureModule<Utils::Utils::StrToSignatureSize(x)>, temp, table); }()
